package com.bigmodel.taskmanager;


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.bigmodel.baidu.BaiduWenXin;
import com.bigmodel.baidu.MarkdownUtil;
import com.bigmodel.util.FtlUtil;
import com.bigmodel.vo.RequestAmdbAttrVO;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class TaskService {

    private final static String TASK_LIST_ATTR_NAME="任务";
    private final static String TASK_ATTR_ID="任务ID";
    private final static String TASK_ATTR_DEPENDENT="依赖任务ID";
    private final static String TASK_ATTR_INPUT="输入";
    private final static String TASK_ATTR_OPERATION="操作";
    private final static String TASK_ATTR_OBSERVE="观察结果";
    private final static String TASK_ATTR_DESCRIBE="任务描述";
    
    private final static String BASE_URL = "http://localhost:8888/api";

    /**执行任务
     *
     * @param taskJson
     */
    public void execute(String taskJson,List<String> answereList){
        JSONObject jsonObject = JSONUtil.parseObj(taskJson);
        JSONArray taskListJson = jsonObject.getJSONArray(TASK_LIST_ATTR_NAME);

        HashMap<String,Object> onceMemory = new HashMap<>();

        /*-----------step1 组装任务链-------------*/
        List<Task> allTask = createTaskChain(taskListJson);

        /*-----------step2 查询第一个任务-------------*/
        Task root = null;
        for(Task task : allTask){
            if("任务1".equals(task.getTaskId())){
                root = task;
            }
        }
        /*-----------step3 创建任务队列-------------*/
        Queue<Task> queue = new LinkedList<>();
        queue.offer(root);

        /*-----------step4 遍历执行任务队列-------------*/
        while (!queue.isEmpty()) {
            Task task = queue.poll();
            System.out.println();
            System.out.println();
            System.out.println();
            System.out.println("AI AGENT: ========================================开始执行新任务==========================================");
            System.out.println("AI AGENT: 我准备做以下任务,"+task.getTaskContent());
            System.out.println("AI AGENT: 任务信息-任务名称["+task.getTaskId()+"]");
            System.out.println("AI AGENT: 任务信息-使用工具["+task.getTaskTool()+"]");
            System.out.println("AI AGENT: 任务信息-输入参数["+task.getInputParam()+"]");
//            System.out.println("AI AGENT: 请输入Y继续执行,N结束");
//            Scanner sc=new Scanner(System.in);
//            String inputLine = sc.nextLine();

            String response = "";
            if(ToolEnum.getDbStatus.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.getDbStatus.getApiUrl());
                response = getDbStatus(task.getInputParam());
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.restartDb.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.restartDb.getApiUrl());
                response = restartDb(task.getInputParam());
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.getInstanceStatus.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.getInstanceStatus.getApiUrl());
                response = getInstanceStatus(task.getInputParam());
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.restartInstance.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.restartInstance.getApiUrl());
                response = restartInstance(task.getInputParam());
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.relationByName.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.relationByName.getApiUrl());
                response = relationByName(task.getInputParam());
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.getAmdbIdByName.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.getAmdbIdByName.getApiUrl());
                response = getAmdbIdByName(task.getInputParam(),onceMemory);
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.getAttrByAmdbId.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.getAttrByAmdbId.getApiUrl());
                JSONObject inputParam = JSONUtil.parseObj(task.getInputParam());
                RequestAmdbAttrVO requestAmdbAttrVO = new RequestAmdbAttrVO();
                requestAmdbAttrVO.setAmdbId(onceMemory.get("amdbId").toString());
                requestAmdbAttrVO.setAttrList(JSONUtil.parseArray(inputParam.getStr("attrList")).toList(String.class));
                response = getAttrByAmdbId(requestAmdbAttrVO,onceMemory);
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.shellLogin.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.shellLogin.getApiUrl());
                response = shellLogin(onceMemory.get("ip").toString(),
                                      onceMemory.get("userName").toString(),
                                      onceMemory.get("passWord").toString(),
                                      onceMemory
                        );
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.deleteFile.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.deleteFile.getApiUrl());
                String fileList = (String) onceMemory.get("fileList");
                response = deleteFile(JSONUtil.toList(fileList,String.class));
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.shellLogout.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.shellLogout.getApiUrl());
                response = shellLogout(onceMemory.get("sessionId").toString());
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.findLog.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.findLog.getApiUrl());
                response = findLog(onceMemory);
                System.out.println("AI AGENT: 执行结果-"+response);
            }else if(ToolEnum.findDiskRate.getName().equals(task.getTaskTool())){
                System.out.println("AI AGENT: 正在调用接口-"+ToolEnum.findDiskRate.getApiUrl());
                response = findDiskRate(task.getInputParam(),onceMemory);
                System.out.println("AI AGENT: 执行结果-"+response);
            }


            answereList.add("我准备这样做:"+task.getTaskContent()+"\r\n");
            answereList.add("我得到的结果:"+response+"\r\n");

            if(ObjectUtil.isEmpty(response)){
                System.out.println("AI AGENT: 执行结果-"+task.getTaskContent());
                break;
            }
            queue.addAll(task.getNextTask());
        }

    }

    /**
     * 组装任务链
     * @param taskListJson
     * @return
     */
    private List<Task> createTaskChain(JSONArray taskListJson){
        List<Task> allTask = new ArrayList<>();
        for(int i = 0 ; i < taskListJson.size() ; i++){
            JSONObject obj = taskListJson.getJSONObject(i);
            Task task = new Task();
            task.setTaskId(obj.getStr(TASK_ATTR_ID));
            task.setTaskName(obj.getStr(TASK_ATTR_OPERATION));
            task.setTaskTool(obj.getStr(TASK_ATTR_OPERATION));
            task.setTaskContent(obj.getStr(TASK_ATTR_DESCRIBE));
            task.setInputParam(obj.getStr(TASK_ATTR_INPUT));
            task.setDependentTaskIds(obj.getJSONArray(TASK_ATTR_DEPENDENT).toList(String.class));
            allTask.add(task);
        }
        Map<String, Task> taskMap = allTask.stream().collect(Collectors.toMap(Task::getTaskId, Function.identity(), (key1, key2) -> key2));

        for(Task task : allTask){
            List<String> dependentTaskIds = task.getDependentTaskIds();
            if(ObjectUtil.isNotEmpty(dependentTaskIds)){
                dependentTaskIds.forEach(taskId->{
                    //获取依赖的前节点
                    Task preTask = taskMap.get(taskId);
                    //绑定前节点的下一节点
                    preTask.addNextTask(task);
                });
            }
        }

        return allTask;
    }


    public static void main(String[] args) {
        String json ="{\n" +
                "    \"目标\": \"CRM系统成功率低于100%的故障处置\",\n" +
                "    \"任务\": [\n" +
                "        {\n" +
                "            \"任务ID\": \"任务1\",\n" +
                "            \"依赖任务ID\": [],\n" +
                "            \"当前上下文\": \"\",\n" +
                "            \"任务描述\": \"使用数据库状态查询工具查看'XX系统'关联数据库的状态\",\n" +
                "            \"操作\": \"数据库状态查询工具\",\n" +
                "            \"输入\": \"XX系统\",\n" +
                "            \"观察结果\": \"返回XX系统状态\"\n" +
                "        },\n" +
                "        {\n" +
                "            \"任务ID\": \"任务2\",\n" +
                "            \"依赖任务ID\": [\"任务1\"],\n" +
                "            \"当前上下文\": \"数据库状态异常\",\n" +
                "            \"任务描述\": \"使用数据库重启工具操作'XX系统'关联数据库\",\n" +
                "            \"操作\": \"数据库重启工具\",\n" +
                "            \"输入\": \"XX系统\",\n" +
                "            \"观察结果\": \"返回XX系统重启结果\"\n" +
                "        },\n" +
                "        {\n" +
                "            \"任务ID\": \"任务3\",\n" +
                "            \"依赖任务ID\": [\"任务1\"],\n" +
                "            \"当前上下文\": \"数据库状态正常\",\n" +
                "            \"任务描述\": \"使用AMDB拓扑关系查询工具查询'XX系统'下的应用实例\",\n" +
                "            \"操作\": \"AMDB拓扑关系查询工具\",\n" +
                "            \"输入\": \"XX系统\",\n" +
                "            \"观察结果\": \"返回XX系统下的实例列表 实例A,实例B\"\n" +
                "        },\n" +
                "        {\n" +
                "            \"任务ID\": \"任务4\",\n" +
                "            \"依赖任务ID\": [\"任务3\"],\n" +
                "            \"当前上下文\": \"\",\n" +
                "            \"任务描述\": \"使用应用实例状态查询工具查询'实例A'的状态\",\n" +
                "            \"操作\": \"应用实例状态查询工具\",\n" +
                "            \"输入\": \"实例A\",\n" +
                "            \"观察结果\": \"返回实例A的状态\"\n" +
                "        },\n" +
                "        {\n" +
                "            \"任务ID\": \"任务5\",\n" +
                "            \"依赖任务ID\": [\"任务3\"],\n" +
                "            \"当前上下文\": \"\",\n" +
                "            \"任务描述\": \"使用应用实例状态查询工具查询'实例B'的状态\",\n" +
                "            \"操作\": \"应用实例状态查询工具\",\n" +
                "            \"输入\": \"实例B\",\n" +
                "            \"观察结果\": \"返回实例B的状态\"\n" +
                "        },\n" +
                "        {\n" +
                "            \"任务ID\": \"任务6\",\n" +
                "            \"依赖任务ID\": [\"任务5\"],\n" +
                "            \"当前上下文\": \"实例B状态异常\",\n" +
                "            \"任务描述\": \"使用实例重启工具对'实例B'进行重启\",\n" +
                "            \"操作\": \"实例重启工具\",\n" +
                "            \"输入\": \"实例B\",\n" +
                "            \"观察结果\": \"返回实例B的重启结果\"\n" +
                "        },\n" +
                "        {\n" +
                "            \"任务ID\": \"任务7\",\n" +
                "            \"依赖任务ID\": [\"任务2\", \"任务6\"],\n" +
                "            \"当前上下文\": \"\",\n" +
                "            \"任务描述\": \"检查数据库或实例状态并判断重启是否成功\",\n" +
                "            \"操作\": \"\",\n" +
                "            \"输入\": \"\",\n" +
                "            \"观察结果\": \"如果数据库或实例状态正常且重启成功，则返回已经成功处理；如果数据库或实例状态异常且重启失败，则返回重启失败\"\n" +
                "        }\n" +
                "    ]\n" +
                "}";

        System.out.println(json);
        TaskService taskService = new TaskService();
       taskService.execute(json,new ArrayList<>());
    }



    
    public String getDbStatus(String  systemName) {
        String url = BASE_URL+"/test/getDbStatus?name="+systemName;
        String result = HttpUtil.get(url);

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        map.put("systemName",systemName);
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/getDbStatus.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }


    
    public String restartDb(String systemName) {
        String url = BASE_URL+"/test/restartDb?name="+systemName;
        String result = HttpUtil.get(url);

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        map.put("systemName",systemName);
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/restartDb.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }

    
    public String relationByName(String systemName) {
        String url = BASE_URL+"/test/relationByName?name="+systemName;
        String result = HttpUtil.get(url);

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        map.put("systemName",systemName);
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/relationByName.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }

    
    public String getInstanceStatus(String instanceName) {
        String url = BASE_URL+"/test/getInstanceStatus?name="+instanceName;
        String result = HttpUtil.get(url);

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        map.put("instanceName",instanceName);
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/getInstanceStatus.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }

    
    public String  restartInstance(String instanceName) {
        String url = BASE_URL+"/test/restartInstance?name="+instanceName;
        String result = HttpUtil.get(url);

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        map.put("instanceName","adminCenter");
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/restartInstance.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }


    public String  getAmdbIdByName(String objectName,HashMap<String,Object> onceMemory) {
        String url = BASE_URL+"/test/getAmdbIdByName?objectName="+objectName;
        String result = HttpUtil.get(url);

        onceMemory.put("amdbId",JSONUtil.parseObj(result).get("data"));

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        map.put("objectName",objectName);
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/getAmdbIdByName.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }


    public String  getAttrByAmdbId(RequestAmdbAttrVO amdbAttrVO,HashMap<String,Object> onceMemory) {
        String url = BASE_URL+"/test/getAttrByAmdbId";
        String result =  HttpUtil.post(url,JSONUtil.toJsonStr(amdbAttrVO));

        JSONObject jsonObject = JSONUtil.parseObj(result);
        JSONObject data = jsonObject.getJSONObject("data");
        onceMemory.put("ip",data.get("ip"));
        onceMemory.put("userName",data.get("userName"));
        onceMemory.put("passWord",data.get("passWord"));

        Map<String, Object> map = new HashMap<>();
        map.put("amdbId",amdbAttrVO.getAmdbId());
        map.put("attrList", JSONUtil.toJsonStr(amdbAttrVO.getAttrList()));
        map.put("apiResponse", result);
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/getAttrByAmdbId.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }


    public String  shellLogin(String ip,String userName,String passWord,HashMap<String,Object> onceMemory) {
        String url = BASE_URL+"/test/shellLogin?ip="+ip+"&userName="+userName+"&passWord="+passWord;
        String result = HttpUtil.get(url);

        JSONObject jsonObject = JSONUtil.parseObj(result);
        onceMemory.put("sessionId",jsonObject.get("data"));

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/shellLogin.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }


    public String  deleteFile(List<String> fileList) {
        String url = BASE_URL+"/test/deleteFile";
        String result = HttpUtil.post(url,JSONUtil.toJsonStr(fileList));

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        map.put("instanceName","adminCenter");
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/deleteFile.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }

    public String  shellLogout(String sessionId) {
        String url = BASE_URL+"/test/shellLogout?sessionId="+sessionId;
        String result = HttpUtil.get(url);

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        map.put("instanceName","adminCenter");
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/shellLogout.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }

    public String  findLog(HashMap<String,Object> onceMemory) {
        String url = BASE_URL+"/test/findLog";
        String result = HttpUtil.get(url);

        onceMemory.put("fileList", JSONUtil.toJsonStr(JSONUtil.parseObj(result).getJSONArray("data")));

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        map.put("instanceName","adminCenter");
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/findLog.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }

    public String  findDiskRate(String objectName,HashMap<String,Object> onceMemory) {
        String url = BASE_URL+"/test/findDiskRate?objectName="+objectName;
        String result = HttpUtil.get(url);

        Map<String, Object> map = new HashMap<>();
        map.put("apiResponse",result);
        map.put("objectName","objectName");
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/findDiskRate.ftl");
        String answerContent = BaiduWenXin.chat(questionContent);
        return answerContent;
    }


    public String receiveQuestion(String questionMessage) {


        Map<String,Object> map = new HashMap<>();
        map.put("faultContent",questionMessage);
        String questionContent = FtlUtil.generateContent(map, "autotask/v1/solution.ftl");

        List<Map<String,String>> messages = new ArrayList<>();
        {
            Map<String, String> messageItem = new HashMap<>();
            messageItem.put("role", "user");
            messageItem.put("content", questionContent);
            messages.add(messageItem);
        }
        String taskPlan = BaiduWenXin.chatList(messages);
        String taskJson = MarkdownUtil.extractJsonText(taskPlan);
        System.out.println("========================================执行计划==========================================");
        System.out.println(taskJson);
        List<String> answereList = new ArrayList<>();
        execute(taskJson,answereList);

        StringBuffer stringBuffer = new StringBuffer();
        for(String string : answereList){
            stringBuffer.append(string);
        }

        Map<String,Object> mapReport = new HashMap<>();
        mapReport.put("content",stringBuffer.toString());
        String report = BaiduWenXin.chat(FtlUtil.generateContent(mapReport, "autotask/v1/createReport.ftl"));
        System.out.println("AI AGENT: 最终报告:"+report);
        return report;

    }
}
